package com.morgan.recyclerviewdemo.itemdecoration

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.view.View
import androidx.annotation.ColorInt
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

/**
 *description：
 *<br>author：caowugao
 *<br>time：2020/7/4 0004 21:32
 */
class LinearItemDecoration(@RecyclerView.Orientation val mOrientation: Int) : RecyclerView.ItemDecoration() {
    private @ColorInt
    var mColor: Int = Color.TRANSPARENT
    private var mDrawable: Drawable? = null
    private var mSize: Int = 0
    private var mIsShowLastItemDecoration: Boolean = false
    private val mPaint: Paint

    private val mMargin = Rect(0, 0, 0, 0)
    private val mItemDecorationRect = Rect(0, 0, 0, 0)

    init {
        mPaint = Paint(Paint.ANTI_ALIAS_FLAG)

    }

    constructor(builder: Builder) : this(builder.mOrientation) {
        this.mColor = builder.mColor
        this.mDrawable = builder.mDrawable
        this.mSize = builder.mSize
        if (this.mDrawable != null && mSize <= 0) {
            mSize = if (mOrientation == RecyclerView.HORIZONTAL) this.mDrawable!!.intrinsicWidth else this.mDrawable!!.intrinsicHeight
        }
        this.mMargin.left = builder.marginLeft
        this.mMargin.top = builder.marginTop
        this.mMargin.right = builder.marginRight
        this.mMargin.bottom = builder.marginBottom

        this.mIsShowLastItemDecoration = builder.mIsShowLastItemDecoration
    }

    class Builder(@RecyclerView.Orientation val mOrientation: Int) {
        @ColorInt
        var mColor: Int = 0
        var mDrawable: Drawable? = null
        var mSize: Int = 0
        var mIsShowLastItemDecoration: Boolean = false
        var marginLeft: Int = 0
        var marginTop: Int = 0
        var marginRight: Int = 0
        var marginBottom: Int = 0

        fun color(@ColorInt color: Int): Builder {
            this.mColor = color
            return this
        }

        fun drawable(drawable: Drawable): Builder {
            this.mDrawable = drawable
            return this
        }

        fun size(size: Int): Builder {
            this.mSize = size
            return this
        }

        fun showLastItemDecoration(value: Boolean): Builder {
            this.mIsShowLastItemDecoration = value
            return this
        }

        fun margin(left: Int, top: Int, right: Int, bottom: Int): Builder {
            this.marginLeft = left
            this.marginTop = top
            this.marginRight = right
            this.marginBottom = bottom
            return this
        }

        fun build(): LinearItemDecoration {
            return LinearItemDecoration(
                this
            )
        }
    }

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        if (mSize <= 0 || parent.adapter == null) {
            super.getItemOffsets(outRect, view, parent, state)
            return
        }

        val position = parent.getChildAdapterPosition(view)
        val itemCount = parent.adapter!!.itemCount
        if (!mIsShowLastItemDecoration && position >= itemCount - 1) {
            return
        }

        when (mOrientation) {
            RecyclerView.HORIZONTAL -> setItemOffsetsHorizontalRect(outRect, view, parent, state)
            RecyclerView.VERTICAL -> setItemOffsetsVerticalRect(outRect, view, parent, state)
            else -> super.getItemOffsets(outRect, view, parent, state)
        }

    }

    private fun setItemOffsetsVerticalRect(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        if (getReverseLayout(parent)) {
            outRect.set(0, mSize + mMargin.top + mMargin.bottom, 0, 0)
        } else {
            outRect.set(0, 0, 0, mSize + mMargin.top + mMargin.bottom)
        }

    }

    private fun getReverseLayout(parent: RecyclerView): Boolean =
        if (parent.layoutManager is LinearLayoutManager) (parent.layoutManager as LinearLayoutManager).getReverseLayout() else false

    private fun setItemOffsetsHorizontalRect(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        if (getReverseLayout(parent)) {
            outRect.set(mSize + mMargin.left + mMargin.right, 0, 0, 0)
        } else {
            outRect.set(0, 0, mSize + mMargin.left + mMargin.right, 0)
        }
    }

    private inline fun hasValidRect(rect: Rect): Boolean =
        rect.left != 0 || rect.top != 0 || rect.right != 0 || rect.bottom != 0

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        if (mSize <= 0 && parent.adapter == null) {
            return
        }

        val childCount = parent.childCount
        val adapter = parent.adapter
        val itemCount = adapter!!.itemCount
        var lastChildPosition = -1
        val itemChildRange = 0 until childCount

        for (i in itemChildRange) {
            val child = parent.getChildAt(i)
            val childPosition = parent.getChildAdapterPosition(child)

            if (childPosition < lastChildPosition) {//动画开始时，无须绘制
                continue
            }
            lastChildPosition = childPosition

            if (!mIsShowLastItemDecoration && childPosition >= itemCount - 1) { //增加是否绘制最后一个itemview的itemDecoration
                continue
            }
            mItemDecorationRect.set(0, 0, 0, 0)
            setDrawItemDecorationRect(childPosition, parent, child)

            if (mDrawable != null) {//优先绘制drawable
                mDrawable!!.setBounds(mItemDecorationRect)
                mDrawable!!.draw(c)
                continue
            }

            mPaint.color = mColor
//            c.drawLine(
//                mItemDecorationRect.left.toFloat(),
//                mItemDecorationRect.top.toFloat(),
//                mItemDecorationRect.right.toFloat(),
//                mItemDecorationRect.bottom.toFloat(),
//                mPaint
//            )
            c.drawRect(mItemDecorationRect, mPaint)


        }

    }

    private fun setDrawItemDecorationRect(
        childPosition: Int,
        parent: RecyclerView,
        child: View?
    ) {
        child ?: return
        when (mOrientation) {
            RecyclerView.HORIZONTAL -> setDrawHorizontalRectParams(childPosition, parent, child)
            RecyclerView.VERTICAL -> setDrawVerticalRectParams(childPosition, parent, child)
            else -> {
            }
        }

    }

    private fun setDrawVerticalRectParams(
        childPosition: Int,
        parent: RecyclerView,
        child: View
    ) {
        val transitionX = child.translationX.toInt()
        val transitionY = child.translationY.toInt()
        val childParams = child.layoutParams as RecyclerView.LayoutParams
        mItemDecorationRect.left =
            parent.paddingLeft + dividerMarginLeft(childPosition, parent) + transitionX
        mItemDecorationRect.right = parent.width - parent.paddingRight - dividerMarginRight(
            childPosition,
            parent
        ) + transitionX

        val dividerSize = getDividerSize(childPosition, parent)
        val isReverseLayout: Boolean = getReverseLayout(parent)
//        val halfSize = dividerSize / 2
//        if (isReverseLayout) {
//            mItemDecorationRect.top = child.top - childParams.topMargin - halfSize + transitionY
//        } else {
//            mItemDecorationRect.top = child.bottom + childParams.bottomMargin + halfSize + transitionY
//        }

        if (isReverseLayout) {
            mItemDecorationRect.top = child.top - childParams.topMargin - dividerMarginBottom(
                childPosition,
                parent
            ) - dividerSize + transitionY
        } else {
            mItemDecorationRect.top = child.bottom + childParams.bottomMargin + dividerMarginTop(
                childPosition,
                parent
            ) + transitionY
        }

        mItemDecorationRect.bottom = mItemDecorationRect.top + dividerSize

    }

    /**
     * 这里可以根据需要，根据某个itemview来进行动态配置 itemDecoration的 MarginRight
     */
    private fun dividerMarginRight(childPosition: Int, parent: RecyclerView): Int = mMargin.right


    /**
     * 这里可以根据需要，根据某个itemview来进行动态配置 itemDecoration的 MarginLeft
     */
    private fun dividerMarginLeft(childPosition: Int, parent: RecyclerView): Int = mMargin.left


    private fun setDrawHorizontalRectParams(
        childPosition: Int,
        parent: RecyclerView,
        child: View
    ) {
        val transitionX = child.translationX.toInt()
        val transitionY = child.translationY.toInt()
        val childParams = child.layoutParams as RecyclerView.LayoutParams
        mItemDecorationRect.top =
            parent.paddingTop + dividerMarginTop(childPosition, parent) + transitionY
        mItemDecorationRect.bottom = parent.height - parent.paddingBottom - dividerMarginBottom(
            childPosition,
            parent
        ) + transitionY

        val dividerSize: Int = getDividerSize(childPosition, parent)
        val isReverseLayout: Boolean = getReverseLayout(parent)

//        val halfSize = dividerSize / 2
//        if (isReverseLayout) {
//            mItemDecorationRect.left = child.left - params.leftMargin - halfSize + transitionX
//        } else {
//            mItemDecorationRect.left = child.right + params.rightMargin + halfSize + transitionX
//        }

        if (isReverseLayout) {
            mItemDecorationRect.left = child.left - childParams.leftMargin - dividerMarginRight(
                childPosition,
                parent
            ) - dividerSize + transitionX
        } else {
            mItemDecorationRect.left = child.right + childParams.rightMargin + dividerMarginLeft(
                childPosition,
                parent
            ) + transitionX
        }

        mItemDecorationRect.right = mItemDecorationRect.left + dividerSize
    }

    /**
     * 这里可以根据需要，根据某个itemview来进行动态配置 itemDecoration的 大小
     */
    private fun getDividerSize(childPosition: Int, parent: RecyclerView): Int = mSize


    /**
     * 这里可以根据需要，根据某个itemview来进行动态配置 itemDecoration的marginBottom
     */
    private fun dividerMarginBottom(childPosition: Int, parent: RecyclerView): Int = mMargin.bottom


    /**
     * 这里可以根据需要，根据某个itemview来进行动态配置 itemDecoration的marginTop
     */
    private fun dividerMarginTop(childPosition: Int, parent: RecyclerView): Int = mMargin.top

}